/*
 * Copyright 2007 Jeffrey Palm
 */

import java.io.*;
import java.util.*;

/**
 * Creates a Perl world
 */
class PerlSink extends AbstractOOSink {

  PerlSink(File outdir) {super(outdir);}

  // --------------------------------------------------
  // AbstractOOSink
  // --------------------------------------------------

  String typeHeader(World.Type t) {return "require 'support.pl';";}


  String typeFooter(World.Type t) {return "return 1;";}

  boolean wantsPublic() {return false;}

  String getExtends() {return null;}

  String formatMember(World.Decl d) {return "$" + d.getName();}

  String constructorStart(String name) {return "sub new";}

  String methodStart(World.Decl d) {return "sub";}

  boolean useParamType() {return false;}

  String thiz(String name) {return "$self->{_" + name + "}";}

  String var(String name) {return "$" + name;}

  String lineComment() {return "#";}

  String comment(String s) {return null;}

  String openBrace() {return "{";}
  String closeBrace() {return "}";}

  void createMethodBody(PrintStream out, World.Type t, World.Decl d) {
    Support.Param[] ps = new Support.Param[d.getParams().size()];
    int i = 0;
    for (World.Param p : d.getParams()) {
      String name = p.getName();
      String value;
      if (p.getType() != null) {
        value = p.getName();
      } else {
        value = getInvokeMethod(t,d.getParams(),p);
      }
      ps[i++] = Support.newParam(name,"' . Support::urlencode(" + value + ") . '"); // unquote it
    }
    String url = Support.getURL(t.getName(),d.getName(),ps, new boolean[]{true,false});
    out.print(tab + tab + "return Support::extractResult('" + url + "');");

  }
  
  /* override */

  boolean wantMembers() {return false;}
  String endClass() {return null;}
  String classHeading(World.Type t) {return "package " + t.getName() + ";";}
  boolean bracesEncloseType() {return false;}
  boolean wantsParams() {return false;}
  String constructorStart(List<World.Decl> decls) {
    String s = "my ($class";
    for (World.Decl d : decls) {
      if (!isAttribute(d)) continue;
      s += ",$" + d.getName();
    }
    s += ") = @_;\n";
    s += "my $self = {";
    return s;
  }
  String constructorEnd() {return "};\nbless $self, $class;\nreturn $self;";}
  String varInit(World.Decl d) {
    return "_" + d.getName() + " => $" + d.getName() + ", #"; // keep a # to cancel out ';'
  }
  String methodThiz(String name) {return "$self->" + name;}
  String methodBegin(World.Type t, World.Decl d) {return "my ($self) = @_;\n";}

  // --------------------------------------------------
  // FileSink
  // --------------------------------------------------

  String getFileName(World.Type t) {
    return t.getName() + ".class.pl";
  }

  String name() {
    return "pl";
  }

  /** Write out include.pl */
  void postpareRest() {
    try {
      PrintStream out = new PrintStream(new FileOutputStream(new File(getOutdir(),"include.pl")));
      for (String n : getFileNames()) {
        out.println("require '" + n + "';");
      }
      out.println("return 1;");
      out.close();
    } catch (Exception e) {e.printStackTrace();}
  }

}